﻿using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using SGP;


namespace NBBL_Tile_Editor
{
    public partial class MainForm : Form
    {
        enum EBrush { TILE_BRUSH, ENT_BRUSH, ENT_SELECT };

        #region Members
        //**********************
        //John-Advised Variables
        private bool looping = true;

        public bool Looping
        {
            get { return looping; }
            set { looping = value; }
        }

        CSGP_Direct3D D3D = CSGP_Direct3D.GetInstance();
        CSGP_TextureManager TM = CSGP_TextureManager.GetInstance();
        //John-Advised Variables
        //**********************

        //General Stuff
        float timer = 0;
        int fps = 60;
        int frames = 0;
        float fpsTimer = 0.0f;

        bool mouseDown = false;

        //Map Info
        string mapName = "New Map";
        Point trCorner = new Point(16, 44); //Starting pos according to default size
        //Size of map in tiles
        Size mapSize = new Size(24, 16);
        //Map's tiles
        Tile[,] map = new Tile[24, 16];
        //Entity map
        Entity[,] entMap = new Entity[24, 16];
        //Stores ball position separately
        Entity ball = new Entity(1, 1, EntityType.BALL);

        //TileSet Info
        string tilePath = "null";
        int tileID = -1;

        // The selected Cannyble
        EnemySpawn selectedCannyble = null;

        //Tileset Size in pizels
        Size tileSetSizeP = new Size(256, 256);
        //TilesetSize in tiles
        Size tileSetSizeT = new Size(8, 8);
        //Each Tile's size in pixels
        Size tileSize = new Size(32, 32);

        //Background Info
        List<string> bgPaths = new List<string>();
        //Other background info will be held in 'listBoxBG'

        //Brush Info
        EBrush brush = EBrush.TILE_BRUSH;

        //Index of Selected Tile
        Point selectedRect = new Point();


        #endregion

        public MainForm()
        {
            InitializeComponent();
            this.Focus();

            D3D.Initialize(tilePanel, false);
            D3D.AddRenderTarget(mapPanel);
            D3D.AddRenderTarget(panelEntPreview);
            D3D.AddRenderTarget(panelTypePreview);

            TM.Initialize(D3D.Device, D3D.Sprite);

            //Set default values
            textBoxMapName.Text = mapName;
            numericUpDownMapW.Value = mapSize.Width;
            numericUpDownMapH.Value = mapSize.Height;

            //AutoScrolls
            if (tileSize.Width * mapSize.Width > 800
                || tileSize.Height * mapSize.Height > 600)
                mapPanel.AutoScrollMinSize = new Size(tileSize.Width * mapSize.Width,
                    tileSize.Height * mapSize.Height);
            else
                mapPanel.AutoScrollMinSize = new Size(800, 600);

            tilePanel.AutoScrollMinSize = tileSetSizeP;

            for (int h = 0; h < mapSize.Height; h++)
            {
                for (int w = 0; w < mapSize.Width; w++)
                {
                    //Sets Tiles
                    map[w, h] = new Tile();

                    //Sets Entities
                    if (w == 0 || h == 0 || w == mapSize.Width - 1 || h == mapSize.Height - 1)
                        entMap[w, h] = new Entity(w, h, EntityType.WALL_INVINCIBLE);
                    else
                        entMap[w, h] = new Entity(w, h, EntityType.ENTITY_BASE);
                }
            }
            //Add core events to the event list
            //Add base tile
            EventString tempES = new EventString();
            tempES.EventColor = Color.WhiteSmoke;
            tempES.EventID = "BASE_TILE";
            cBTileType.Items.Add(tempES);
            //Add slow hazard tile
            tempES = new EventString();
            tempES.EventColor = Color.Fuchsia;
            tempES.EventID = "SLOW_HAZARD";
            cBTileType.Items.Add(tempES);
            //Add damage hazard tile
            tempES = new EventString();
            tempES.EventColor = Color.Orange;
            tempES.EventID = "DAMAGE_HAZARD";
            cBTileType.Items.Add(tempES);
            //Add  red goal
            tempES = new EventString();
            tempES.EventColor = Color.Red;
            tempES.EventID = "RED_GOAL";
            cBTileType.Items.Add(tempES);
            //Add blue goal
            tempES = new EventString();
            tempES.EventColor = Color.Blue;
            tempES.EventID = "BLUE_GOAL";
            cBTileType.Items.Add(tempES);

            cBTileType.SelectedIndex = 0;
        }

        public void Update(float dt)
        {
            //Timer info
            timer += dt;

            frames++;
            fpsTimer += dt;
            if (fpsTimer > 1.0f) //Refresh every second
            {
                fps = frames;
                frames = 0;
                fpsTimer = 0.0f;
            }

            //Sync Saved Values with Input Fields
            tileSize.Width = (int)(numericUpDownTW.Value);
            tileSize.Height = (int)(numericUpDownTH.Value);
            //If larger than 800 x 600 uses 0,0 as origin
            if ((mapSize.Width * tileSize.Width) > 800 || (mapSize.Height * tileSize.Height) > 600)
                trCorner = new Point(0, 0);
            //Center the arena if it fits within the target resolution
            else
                trCorner = new Point((800 - (mapSize.Width * tileSize.Width)) / 2, (600 - (mapSize.Height * tileSize.Height)) / 2);

            mapName = textBoxMapName.Text;
        }

        #region Rendering
        //Renders stuff
        public void Render()
        {
            //Render each window that needs rendering
            RenderTiles();
            RenderMap();
            RenderEntPreview();
            RenderTileTypePreview();
        }

        void RenderMap()
        {
            //Render the map
            D3D.Clear(mapPanel, Color.White);

            Point offset = new Point(0, 0);

            D3D.DeviceBegin();
            D3D.SpriteBegin();

            //Render Background
            if (bgPaths.Count > 0 && listBoxBG.Items.Count > 0)
            {
                for (int i = 0; i < listBoxBG.Items.Count; i++)
                {
                    BackgroundLayer dummy = (BackgroundLayer)listBoxBG.Items[i];
                    if (!dummy.Visible)
                        continue;

                    offset.X = (int)(mapPanel.AutoScrollPosition.X * dummy.ParaSpeed);
                    offset.Y = (int)(mapPanel.AutoScrollPosition.Y * dummy.ParaSpeed);

                    if (dummy.TextureID != -1)
                    {
                        if (!dummy.Loop)
                            TM.Draw(dummy.TextureID, dummy.Location.X + offset.X,
                               dummy.Location.Y + offset.Y, 1.0f, 1.0f, Rectangle.Empty);

                        //Connects background wherever it ends
                        else if (dummy.Loop)
                        {
                            //To the left
                            Point test = dummy.Location;
                            while (test.X > offset.X)
                                test.X -= dummy.Size.Width;
                            while (test.Y > offset.Y)
                                test.Y -= dummy.Size.Height;

                            Point corner = test;

                            test = new Point();
                            test.Y = corner.Y + offset.Y;
                            //Below and to the right
                            do
                            {
                                test.X = corner.X + offset.X;
                                while (test.X < mapPanel.Width)
                                {
                                    TM.Draw(dummy.TextureID, test.X,
                                        test.Y, 1.0f, 1.0f, Rectangle.Empty);
                                    test.X += dummy.Size.Width;
                                }
                                test.Y += dummy.Size.Height;

                            } while (test.Y < mapPanel.Height);
                        }
                    }
                }
            }
            offset.X += mapPanel.AutoScrollPosition.X;
            offset.Y += mapPanel.AutoScrollPosition.Y;

            Point tempPoint = trCorner;
            tempPoint.X += offset.X;
            tempPoint.Y += offset.Y;
            Rectangle grid = new Rectangle(tempPoint, tileSize);
            //Draw Map tiles here
            {
                //Render the tiles in the map
                for (int h = 0; h < mapSize.Height; h++)
                {
                    grid.X = tempPoint.X;
                    for (int w = 0; w < mapSize.Width; w++)
                    {
                        if (mapSize.Width > w && mapSize.Height > h)
                        {
                            //Tile accessing rect outside of image
                            if (map[w, h].X >= tileSetSizeT.Width || map[w, h].Y >= tileSetSizeT.Height)
                                D3D.DrawRect(grid, Color.Tomato);
                            //Normal Rendering of Map
                            if (tileID != -1 && showTilesToolStripMenuItem.Checked)
                            {
                                //Portion of image file to be rendered
                                Rectangle srcRect = Rectangle.Empty;
                                srcRect.X = map[w, h].X * tileSize.Width;
                                srcRect.Y = map[w, h].Y * tileSize.Height;
                                srcRect.Width = tileSize.Width;
                                srcRect.Height = tileSize.Height;

                                TM.Draw(tileID, grid.X, grid.Y, 1.0f, 1.0f, srcRect);
                            }
                            //If viewing by type, not tile
                            if (showTileTypeToolStripMenuItem.Checked)
                            {
                                //Render based on eventColor
                                D3D.DrawRect(grid, Color.FromArgb(160, ((EventString)cBTileType.Items[map[w, h].Id]).EventColor));
                            }
                        }
                        grid.X += grid.Width;
                    }
                    grid.Y += grid.Height;
                }
            }

            //Render Entities

            Size entMapSize = new Size(mapSize.Width * tileSize.Width / 32, mapSize.Height * tileSize.Height / 32);
            if (showEntitiesToolStripMenuItem.Checked)
            {
                tempPoint = trCorner;
                tempPoint.X += offset.X;
                tempPoint.Y += offset.Y;
                Rectangle smallRect = new Rectangle(tempPoint.X + 10, tempPoint.Y + 10, 12, 12);
                Rectangle bigRect = new Rectangle(tempPoint.X + 5, tempPoint.Y + 5, 22, 22);

                for (int h = 0; h < entMapSize.Height; h++)
                {
                    bigRect.X = tempPoint.X + 5;
                    smallRect.X = tempPoint.X + 10;
                    for (int w = 0; w < entMapSize.Width; w++)
                    {
                        //Red Player
                        if (entMap[w, h].Type == EntityType.PLAYER_RED)
                        {
                            D3D.DrawHollowRect(bigRect, Color.DarkRed, 6);
                        }
                        //Blue player
                        else if (entMap[w, h].Type == EntityType.PLAYER_BLUE)
                        {
                            D3D.DrawHollowRect(bigRect, Color.DarkBlue, 6);
                        }
                        //Gorbachev
                        else if (entMap[w, h].Type == EntityType.ENEMY_GORBACHEV)
                        {
                            D3D.DrawHollowRect(bigRect, Color.DarkOrange, 6);
                            D3D.DrawLine(bigRect.Left, bigRect.Top, bigRect.Right, bigRect.Bottom, Color.Gold, 3);
                            D3D.DrawLine(bigRect.Right, bigRect.Top, bigRect.Left, bigRect.Bottom, Color.Gold, 3);
                        }
                        //Cannyble
                        else if (entMap[w, h].Type == EntityType.ENEMY_CANNYBLE)
                        {
                            D3D.DrawHollowRect(smallRect, Color.DarkOrange, 6);
                        }
                        //Invincible Wall
                        else if (entMap[w, h].Type == EntityType.WALL_INVINCIBLE)
                        {
                            D3D.DrawHollowRect(bigRect, Color.Black, 6);
                            D3D.DrawLine(bigRect.Left, bigRect.Top, bigRect.Right, bigRect.Bottom, Color.Black, 3);
                            D3D.DrawLine(bigRect.Right, bigRect.Top, bigRect.Left, bigRect.Bottom, Color.Black, 3);
                        }
                        //Tall Wall
                        else if (entMap[w, h].Type == EntityType.WALL_TALL)
                        {
                            D3D.DrawHollowRect(bigRect, Color.Gray, 6);
                            D3D.DrawLine(bigRect.Left, bigRect.Top, bigRect.Right, bigRect.Bottom, Color.Gray, 3);
                            D3D.DrawLine(bigRect.Right, bigRect.Top, bigRect.Left, bigRect.Bottom, Color.Gray, 3);
                        }
                        //Short Wall
                        else if (entMap[w, h].Type == EntityType.WALL_SHORT)
                        {
                            D3D.DrawHollowRect(bigRect, Color.LightGray, 6);
                            D3D.DrawLine(bigRect.Left, bigRect.Top, bigRect.Right, bigRect.Bottom, Color.LightGray, 3);
                            D3D.DrawLine(bigRect.Right, bigRect.Top, bigRect.Left, bigRect.Bottom, Color.LightGray, 3);
                        }
                        //Power-Up
                        else if (entMap[w, h].Type == EntityType.PUP)
                        {
                            D3D.DrawHollowRect(smallRect, Color.GreenYellow, 6);
                        }

                        bigRect.X += 32;
                        smallRect.X += 32;
                    }
                    bigRect.Y += 32;
                    smallRect.Y += 32;
                }

                // Waypoints
                if (selectedCannyble != null)
                {
                    for (int waypoints = 0; waypoints < selectedCannyble.Waypoints.Count; waypoints++)
                    {
                        smallRect.X = 10 + tempPoint.X + 32 * selectedCannyble.Waypoints[waypoints].X;
                        smallRect.Y = 10 + tempPoint.Y + 32 * selectedCannyble.Waypoints[waypoints].Y;
                        Rectangle tempRect = new Rectangle(selectedCannyble.X, selectedCannyble.Y, 16, 16);
                        D3D.DrawHollowRect(smallRect, Color.Azure, 6);
                    }
                }

                //Draw ball
                smallRect.X = 10 + tempPoint.X + 32 * ball.X;
                smallRect.Y = 10 + tempPoint.Y + 32 * ball.Y;
                D3D.DrawRect(smallRect, Color.Goldenrod);
                D3D.DrawHollowRect(smallRect, Color.Gold, 3);
            }

            //Render Map grid
            if (showTileGridToolStripMenuItem.Checked)
            {
                tempPoint = trCorner;
                tempPoint.X += offset.X;
                tempPoint.Y += offset.Y;
                grid = new Rectangle(tempPoint, tileSize);
                //Draw Map grid here
                for (int i = 0; i < mapSize.Height; i++)
                {
                    grid.X = trCorner.X + offset.X;
                    for (int j = 0; j < mapSize.Width; j++)
                    {
                        if (showEntityGridToolStripMenuItem.Checked)
                            D3D.DrawHollowRect(grid, Color.Black, 2);
                        else
                            D3D.DrawHollowRect(grid, Color.Black, 2);
                        grid.X += grid.Width;
                    }
                    grid.Y += grid.Height;
                }
            }
            //Render Entity Grid
            if (showEntityGridToolStripMenuItem.Checked)
            {
                tempPoint = trCorner;
                tempPoint.X += offset.X;
                tempPoint.Y += offset.Y;
                grid = new Rectangle(tempPoint.X, tempPoint.Y, 32, 32);
                //Draw Entity grid here
                for (int i = 0; i < entMapSize.Height; i++)
                {
                    grid.X = trCorner.X + offset.X;
                    for (int j = 0; j < entMapSize.Width; j++)
                    {
                        D3D.DrawHollowRect(grid, Color.Pink, 1);
                        grid.X += grid.Width;
                    }
                    grid.Y += grid.Height;
                }
            }


            D3D.SpriteEnd();
            D3D.DeviceEnd();
            D3D.Present();
        }

        void RenderTiles()
        {
            //Render the tile page
            D3D.Clear(tilePanel, Color.White);

            Point offset = new Point(0, 0);

            offset.X += tilePanel.AutoScrollPosition.X;
            offset.Y += tilePanel.AutoScrollPosition.Y;

            D3D.DeviceBegin();
            D3D.SpriteBegin();

            //Render Tileset here
            if (tileID != -1 && tabControl1.SelectedIndex == 1)
            {
                Rectangle tempRect = Rectangle.Empty;

                TM.Draw(tileID, offset.X, offset.Y, 1.0f, 1.0f, tempRect);
            }

            //Render grid here
            Point tempPoint = offset;
            Rectangle grid = new Rectangle(tempPoint, tileSize);
            for (int i = 0; i < tileSetSizeT.Height; i++)
            {
                grid.X = offset.X;
                for (int j = 0; j < tileSetSizeT.Width; j++)
                {
                    D3D.DrawHollowRect(grid, Color.Black, 1);
                    grid.X += grid.Width;
                }
                grid.Y += grid.Height;
            }

            //Render Selected Tile here
            grid = new Rectangle(tempPoint, tileSize);

            grid.X += selectedRect.X * tileSize.Width;
            grid.Y += selectedRect.Y * tileSize.Height;

            D3D.DrawHollowRect(grid, Color.Cyan, 1);

            D3D.SpriteEnd();
            D3D.DeviceEnd();

            D3D.Present();
        }

        void RenderEntPreview()
        {
            //Render the map
            D3D.Clear(panelEntPreview, Color.White);

            Point offset = new Point(0, 0);

            D3D.DeviceBegin();
            D3D.SpriteBegin();

            Rectangle fullRect = new Rectangle(5, 5, 28, 28);
            Rectangle smallRect = new Rectangle(5, 5, 12, 12);
            Point tl = new Point(5, 5);
            Point tr = new Point(33, 5);
            Point bl = new Point(5, 33);
            Point br = new Point(33, 33);

            //Red Player
            if (cBEntType.SelectedIndex == 1)
            {
                D3D.DrawHollowRect(fullRect, Color.DarkRed, 6);
            }
            //Blue player
            else if (cBEntType.SelectedIndex == 2)
            {
                D3D.DrawHollowRect(fullRect, Color.DarkBlue, 6);
            }
            //Gorbachev
            else if (cBEntType.SelectedIndex == 3)
            {
                D3D.DrawHollowRect(fullRect, Color.DarkOrange, 6);
                D3D.DrawLine(tl.X, tl.Y, bl.X, br.Y, Color.Gold, 3);
                D3D.DrawLine(tr.X, tr.Y, bl.X, bl.Y, Color.Gold, 3);
            }
            //Cannyble
            else if (cBEntType.SelectedIndex == 4)
            {
                D3D.DrawHollowRect(smallRect, Color.DarkOrange, 6);
            }
            //Invincible Wall
            else if (cBEntType.SelectedIndex == 5)
            {
                D3D.DrawHollowRect(fullRect, Color.Black, 6);
                D3D.DrawLine(tl.X, tl.Y, br.X, br.Y, Color.Black, 3);
                D3D.DrawLine(tr.X, tr.Y, bl.X, bl.Y, Color.Black, 3);
            }
            //Tall Wall
            else if (cBEntType.SelectedIndex == 6)
            {
                D3D.DrawHollowRect(fullRect, Color.Gray, 6);
                D3D.DrawLine(tl.X, tl.Y, br.X, br.Y, Color.Gray, 3);
                D3D.DrawLine(tr.X, tr.Y, bl.X, bl.Y, Color.Gray, 3);
            }
            //Short Wall
            else if (cBEntType.SelectedIndex == 7)
            {
                D3D.DrawHollowRect(fullRect, Color.LightGray, 6);
                D3D.DrawLine(tl.X, tl.Y, br.X, br.Y, Color.LightGray, 3);
                D3D.DrawLine(tr.X, tr.Y, bl.X, bl.Y, Color.LightGray, 3);
            }
            //Power-Up
            else if (cBEntType.SelectedIndex == 8)
            {
                D3D.DrawHollowRect(smallRect, Color.GreenYellow, 6);
            }
            //Ball
            else if (cBEntType.SelectedIndex == 9)
            {
                D3D.DrawRect(smallRect, Color.Goldenrod);
                D3D.DrawHollowRect(smallRect, Color.Gold, 3);
            }


            D3D.SpriteEnd();
            D3D.DeviceEnd();

            D3D.Present();
        }

        void RenderTileTypePreview()
        {
            if (cBTileType.SelectedIndex == -1)
                cBTileType.SelectedIndex = 0;

            D3D.Clear(panelTypePreview, ((EventString)cBTileType.Items[cBTileType.SelectedIndex]).EventColor);

            D3D.Present();

        }

        #endregion

        //Ends game loop when form closes
        private void CloseForm(object sender, FormClosingEventArgs e)
        {
            Looping = false;

        }

        //When Exit is Selected from the file menu
        private void ExitForm(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Reset ALL variables to default values
            textBoxMapName.Text = mapName = "New Map";
            numericUpDownMapW.Value = 24;
            numericUpDownMapH.Value = 16;

            numericUpDownTW.Value = numericUpDownTH.Value = 32;

            if (tilePath != "null")
            {
                tilePath = "null";
                tileID = -1;
                tileSetSizeP = new Size(256, 256);
                tileSetSizeT = new Size(8, 8);
            }
            //Clears out paths to strings
            bgPaths.Clear();

            //Clear all textures and restart texture manager
            TM.Terminate();
            TM.Initialize(D3D.Device, D3D.Sprite);

            //Clears out background layer information
            listBoxBG.Items.Clear();

            selectedRect = new Point();

            //AutoScrolls
            tilePanel.AutoScrollMinSize = tileSetSizeP;

            showTileTypeToolStripMenuItem.Checked = false;

            buttonClear_Click(sender, e);
        }

        #region File I/O
        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Sets to Resources/Map if not already there
            if (Directory.Exists("..//..//..//..//..//..//NationalBombBallLeague//NationalBombBallLeague//Resources//Maps"))
                Directory.SetCurrentDirectory("..//..//..//..//..//..//NationalBombBallLeague//NationalBombBallLeague//Resources//Maps");

            //Save a map in xml here
            SaveFileDialog saveBox = new SaveFileDialog();
            saveBox.Filter = "XML Files(*.xml*)|*.xml*";
            saveBox.DefaultExt = ".xml";

            saveBox.InitialDirectory = Directory.GetCurrentDirectory();

            if (saveBox.ShowDialog() == DialogResult.OK)
            {
                string tempS;
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = true;

                XmlWriter writer = XmlWriter.Create(saveBox.FileName, settings);
                //Begins the document
                writer.WriteStartDocument();
                //Establishes root element
                writer.WriteStartElement("Map");
                //Map Name
                writer.WriteStartElement("MapName");
                writer.WriteString(textBoxMapName.Text);
                writer.WriteEndElement();
                //Backgrounds
                writer.WriteStartElement("Backgrounds");
                writer.WriteAttributeString("layers", listBoxBG.Items.Count.ToString());
                //For each layer
                for (int i = 0; i < listBoxBG.Items.Count; i++)
                {
                    //Get each layer
                    BackgroundLayer dummy = (BackgroundLayer)(listBoxBG.Items[i]);
                    //Write Layer
                    writer.WriteStartElement("Layer");
                    //Write layer name
                    writer.WriteStartElement("Name");
                    writer.WriteString(dummy.Name);
                    writer.WriteEndElement();
                    //Write layer source file
                    writer.WriteStartElement("Source");
                    //Remove the directory
                    tempS = bgPaths[dummy.TextureIndex];
                    if (tempS.Contains('\\'))
                        tempS = tempS.Remove(0, tempS.LastIndexOf('\\') + 1);
                    writer.WriteString(tempS);
                    writer.WriteEndElement();
                    //Write Parrallax section
                    writer.WriteStartElement("Parallax");
                    //Write vis bool
                    if (dummy.Visible)
                        writer.WriteAttributeString("vis", "1");
                    else
                        writer.WriteAttributeString("vis", "0");
                    //Write float and ints
                    writer.WriteAttributeString("intensity", dummy.ParaSpeed.ToString());
                    writer.WriteAttributeString("x", dummy.Location.X.ToString());
                    writer.WriteAttributeString("y", dummy.Location.Y.ToString());
                    //Write wrap bool
                    if (dummy.Loop)
                        writer.WriteAttributeString("wrap", "1");
                    else
                        writer.WriteAttributeString("wrap", "0");
                    writer.WriteAttributeString("w", dummy.Size.Width.ToString());
                    writer.WriteAttributeString("h", dummy.Size.Height.ToString());

                    //End the Parallax                
                    writer.WriteEndElement();
                    //End the Layer
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();

                //Tiles
                writer.WriteStartElement("Tiles");
                //Tile and map width
                writer.WriteAttributeString("tileW", tileSize.Width.ToString());
                writer.WriteAttributeString("tileH", tileSize.Height.ToString());
                writer.WriteAttributeString("mapW", mapSize.Width.ToString());
                writer.WriteAttributeString("mapH", mapSize.Height.ToString());
                //Tileset source file
                writer.WriteStartElement("TileSet");
                //Remove the directory
                tempS = tilePath;
                if (tempS.Contains('\\'))
                    tempS = tempS.Remove(0, tempS.LastIndexOf('\\') + 1);
                writer.WriteString(tempS);
                writer.WriteEndElement();
                //Tile Events / Types
                writer.WriteStartElement("Events");
                writer.WriteAttributeString("count", cBTileType.Items.Count.ToString());
                //For each event
                for (int i = 0; i < cBTileType.Items.Count; i++)
                {
                    EventString dummy = (EventString)(cBTileType.Items)[i];
                    //Write out each Event
                    writer.WriteStartElement("Event");
                    writer.WriteAttributeString("type", dummy.EventID);
                    writer.WriteAttributeString("r", dummy.EventColor.R.ToString());
                    writer.WriteAttributeString("g", dummy.EventColor.G.ToString());
                    writer.WriteAttributeString("b", dummy.EventColor.B.ToString());
                    writer.WriteEndElement();
                }
                //End Events
                writer.WriteEndElement();

                //For each Row
                for (int h = 0; h < mapSize.Height; h++)
                {
                    //Start the row
                    writer.WriteStartElement("Row");
                    //For each Column
                    for (int w = 0; w < mapSize.Width; w++)
                    {
                        //Write out the Tile
                        writer.WriteStartElement("Tile");
                        writer.WriteAttributeString("event", map[w, h].Id.ToString());
                        int tempInt = map[w, h].Y * tileSetSizeT.Width + map[w, h].X;
                        writer.WriteAttributeString("source", tempInt.ToString());
                        writer.WriteEndElement();
                    }
                    //End the row
                    writer.WriteEndElement();
                }
                //End the Tiles
                writer.WriteEndElement();

                //Count the Entities
                int rp = 0, bp = 0, eb = 0, ec = 0, wi = 0, wt = 0, ws = 0;
                Size entMapSize = new Size(mapSize.Width * tileSize.Width / 32, mapSize.Height * tileSize.Height / 32);

                //For every row of entities
                for (int h = 0; h < entMapSize.Height; h++)
                {
                    //For every column of entities
                    for (int w = 0; w < entMapSize.Width; w++)
                    {
                        if (entMap[w, h].Type == EntityType.PLAYER_RED)
                            rp++;
                        else if (entMap[w, h].Type == EntityType.PLAYER_BLUE)
                            bp++;
                        else if (entMap[w, h].Type == EntityType.ENEMY_GORBACHEV)
                            eb++;
                        else if (entMap[w, h].Type == EntityType.ENEMY_CANNYBLE)
                            ec++;
                        else if (entMap[w, h].Type == EntityType.WALL_INVINCIBLE)
                            wi++;
                        else if (entMap[w, h].Type == EntityType.WALL_TALL)
                            wt++;
                        else if (entMap[w, h].Type == EntityType.WALL_SHORT)
                            ws++;
                    }
                }
                //Start writing entities
                writer.WriteStartElement("Entities");
                //Write out ball
                writer.WriteStartElement("Ball");
                writer.WriteAttributeString("x", ball.X.ToString());
                writer.WriteAttributeString("y", ball.Y.ToString());
                writer.WriteEndElement();
                //Write out red players
                writer.WriteStartElement("RedPlayers");
                writer.WriteAttributeString("count", rp.ToString());
                if (rp > 0)
                {
                    for (int h = 0; h < entMapSize.Height; h++)
                    {
                        //For every column of entities
                        for (int w = 0; w < entMapSize.Width; w++)
                        {
                            if (entMap[w, h].Type == EntityType.PLAYER_RED)
                            {
                                //Write out an instance
                                writer.WriteStartElement("Instance");
                                writer.WriteAttributeString("x", entMap[w, h].X.ToString());
                                writer.WriteAttributeString("y", entMap[w, h].Y.ToString());
                                writer.WriteEndElement();
                                rp--;
                            }
                            if (rp == 0)
                                break;
                        }
                    }
                }
                writer.WriteEndElement();

                //Write out blue players
                writer.WriteStartElement("BluePlayers");
                writer.WriteAttributeString("count", bp.ToString());
                if (bp > 0)
                {
                    for (int h = 0; h < entMapSize.Height; h++)
                    {
                        //For every column of entities
                        for (int w = 0; w < entMapSize.Width; w++)
                        {
                            if (entMap[w, h].Type == EntityType.PLAYER_BLUE)
                            {
                                //Write out an instance
                                writer.WriteStartElement("Instance");
                                writer.WriteAttributeString("x", entMap[w, h].X.ToString());
                                writer.WriteAttributeString("y", entMap[w, h].Y.ToString());
                                writer.WriteEndElement();
                                bp--;
                            }
                            if (bp == 0)
                                break;
                        }
                    }
                }
                writer.WriteEndElement();

                //Write out bosses
                writer.WriteStartElement("Boss");
                writer.WriteAttributeString("count", eb.ToString());
                if (eb > 0)
                {
                    for (int h = 0; h < entMapSize.Height; h++)
                    {
                        //For every column of entities
                        for (int w = 0; w < entMapSize.Width; w++)
                        {
                            if (entMap[w, h].Type == EntityType.ENEMY_GORBACHEV)
                            {
                                //Write out an instance
                                writer.WriteStartElement("Instance");
                                writer.WriteAttributeString("x", entMap[w, h].X.ToString());
                                writer.WriteAttributeString("y", entMap[w, h].Y.ToString());
                                writer.WriteEndElement();
                                eb--;
                            }
                            if (eb == 0)
                                break;
                        }
                    }
                }
                writer.WriteEndElement();

                //Write out enemies
                writer.WriteStartElement("Enemies");
                writer.WriteAttributeString("count", ec.ToString());
                if (ec > 0)
                {
                    for (int h = 0; h < entMapSize.Height; h++)
                    {
                        //For every column of entities
                        for (int w = 0; w < entMapSize.Width; w++)
                        {
                            if (entMap[w, h].Type == EntityType.ENEMY_CANNYBLE)
                            {
                                //Write out an instance
                                writer.WriteStartElement("Instance");
                                writer.WriteAttributeString("x", entMap[w, h].X.ToString());
                                writer.WriteAttributeString("y", entMap[w, h].Y.ToString());
                                writer.WriteAttributeString("NumWaypoints", new EnemySpawn(entMap[w, h].X, entMap[w, h].Y, entMap[w, h].Type).Waypoints.Count.ToString());
                                for (int waypoints = 0; waypoints < new EnemySpawn(entMap[w, h].X, entMap[w, h].Y, entMap[w, h].Type).Waypoints.Count; waypoints++)
                                {
                                    writer.WriteAttributeString("WaypointX", ((EnemySpawn)entMap[w, h]).Waypoints[waypoints].X.ToString());
                                    writer.WriteAttributeString("WaypointY", ((EnemySpawn)entMap[w, h]).Waypoints[waypoints].Y.ToString());
                                }
                                writer.WriteEndElement();
                                ec--;
                            }
                            if (ec == 0)
                                break;
                        }
                    }
                }
                writer.WriteEndElement();

                //Write out invincible walls
                writer.WriteStartElement("WallsInvincible");
                writer.WriteAttributeString("count", wi.ToString());
                if (wi > 0)
                {
                    for (int h = 0; h < entMapSize.Height; h++)
                    {
                        //For every column of entities
                        for (int w = 0; w < entMapSize.Width; w++)
                        {
                            if (entMap[w, h].Type == EntityType.WALL_INVINCIBLE)
                            {
                                //Write out an instance
                                writer.WriteStartElement("Instance");
                                writer.WriteAttributeString("x", entMap[w, h].X.ToString());
                                writer.WriteAttributeString("y", entMap[w, h].Y.ToString());
                                writer.WriteEndElement();
                                wi--;
                            }
                            if (wi == 0)
                                break;
                        }
                    }
                }
                writer.WriteEndElement();

                //Write out tall walls
                writer.WriteStartElement("WallsTall");
                writer.WriteAttributeString("count", wt.ToString());
                if (wt > 0)
                {
                    for (int h = 0; h < entMapSize.Height; h++)
                    {
                        //For every column of entities
                        for (int w = 0; w < entMapSize.Width; w++)
                        {
                            if (entMap[w, h].Type == EntityType.WALL_TALL)
                            {
                                //Write out an instance
                                writer.WriteStartElement("Instance");
                                writer.WriteAttributeString("x", entMap[w, h].X.ToString());
                                writer.WriteAttributeString("y", entMap[w, h].Y.ToString());
                                writer.WriteEndElement();
                                wt--;
                            }
                            if (wt == 0)
                                break;
                        }
                    }
                }
                writer.WriteEndElement();

                //Write out short walls
                writer.WriteStartElement("WallsShort");
                writer.WriteAttributeString("count", ws.ToString());
                if (ws > 0)
                {
                    for (int h = 0; h < entMapSize.Height; h++)
                    {
                        //For every column of entities
                        for (int w = 0; w < entMapSize.Width; w++)
                        {
                            if (entMap[w, h].Type == EntityType.WALL_SHORT)
                            {
                                //Write out an instance
                                writer.WriteStartElement("Instance");
                                writer.WriteAttributeString("x", entMap[w, h].X.ToString());
                                writer.WriteAttributeString("y", entMap[w, h].Y.ToString());
                                writer.WriteEndElement();
                                ws--;
                            }
                            if (ws == 0)
                                break;
                        }
                    }
                }
                writer.WriteEndElement();

                //End Entities
                writer.WriteEndElement();

                //End Map (finally)
                writer.WriteEndElement();
                //End document
                writer.WriteEndDocument();
                writer.Flush();
                writer.Close();
            }
        }

        private void loadMapToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Sets to Resources/Map if not already there
            if (Directory.Exists("..//..//..//..//..//..//NationalBombBallLeague//NationalBombBallLeague//Resources//Maps"))
                Directory.SetCurrentDirectory("..//..//..//..//..//..//NationalBombBallLeague//NationalBombBallLeague//Resources//Maps");

            //Load a map in xml here
            OpenFileDialog openBox = new OpenFileDialog();
            openBox.Filter = "XML Files(*.xml*)|*.xml*";
            //openBox
            if (DialogResult.OK == openBox.ShowDialog())
            {
                openBox.InitialDirectory = Directory.GetCurrentDirectory();
                //Clear out all values
                newToolStripMenuItem_Click(sender, e);

                XmlTextReader reader = new XmlTextReader(openBox.FileName);

                if (reader.Read())
                {
                    //Set up temporary storage containers
                    int tempInt = 0;
                    Bitmap tempBM;
                    string tempString;

                    //Start with the root
                    reader.ReadToFollowing("Map");
                    //Read the name of the map
                    reader.ReadToFollowing("MapName");
                    textBoxMapName.Text = mapName = reader.ReadElementContentAsString();

                    //Read the background information
                    reader.ReadToNextSibling("Backgrounds");
                    reader.MoveToFirstAttribute();
                    tempInt = Int32.Parse(reader.Value);

                    //For every background layer
                    for (int i = 0; i < tempInt; i++)
                    {
                        BackgroundLayer tempBGL = new BackgroundLayer();
                        //Get the name of the layer
                        reader.ReadToFollowing("Name");
                        tempBGL.Name = reader.ReadElementContentAsString();
                        //Get the source file of the layer
                        reader.ReadToFollowing("Source");
                        tempString = reader.ReadElementContentAsString();
                        bgPaths.Add(tempString);
                        tempBM = new Bitmap(tempString);
                        tempBGL.Size = tempBM.Size;
                        tempBGL.TextureID = TM.LoadTexture(tempString);
                        //Parrallax and coord information
                        reader.ReadToFollowing("Parallax");
                        //Visibility
                        reader.MoveToFirstAttribute();
                        tempBGL.Visible = Int32.Parse(reader.Value) == 1;
                        //Intensity
                        reader.MoveToNextAttribute();
                        tempBGL.ParaSpeed = float.Parse(reader.Value);
                        //Position
                        reader.MoveToNextAttribute();
                        Point tempPoint = new Point(0, 0);
                        tempPoint.X = Int32.Parse(reader.Value);
                        reader.MoveToNextAttribute();
                        tempPoint.Y = Int32.Parse(reader.Value);
                        tempBGL.Location = tempPoint;
                        //Wrap
                        reader.MoveToNextAttribute();
                        tempBGL.Loop = Int32.Parse(reader.Value) == 1;
                        Size tempSize = new Size();
                        reader.MoveToNextAttribute();
                        tempSize.Width = Int32.Parse(reader.Value);
                        reader.MoveToNextAttribute();
                        tempSize.Height = Int32.Parse(reader.Value);
                        tempBGL.Size = tempSize;
                        //Texture id
                        tempBGL.TextureIndex = i;

                        //Save tempBGL
                        listBoxBG.Items.Add(tempBGL);
                    }
                    //Start reading Tile information
                    reader.ReadToFollowing("Tiles");

                    //Read tile dimensions
                    reader.MoveToFirstAttribute();
                    numericUpDownTW.Value = tileSize.Width = Int32.Parse(reader.Value);
                    reader.MoveToNextAttribute();
                    numericUpDownTH.Value = tileSize.Height = Int32.Parse(reader.Value);

                    //Read Map dimensions
                    reader.MoveToNextAttribute();
                    numericUpDownMapW.Value = Int32.Parse(reader.Value);
                    reader.MoveToNextAttribute();
                    numericUpDownMapH.Value = Int32.Parse(reader.Value);

                    //Establish blank map
                    map = new Tile[mapSize.Width, mapSize.Height];

                    for (int h = 0; h < mapSize.Height; h++)
                    {
                        for (int w = 0; w < mapSize.Width; w++)
                        {
                            map[w, h] = new Tile();
                        }
                    }

                    //Read Tile file name
                    reader.ReadToFollowing("TileSet");
                    tilePath = reader.ReadElementContentAsString();
                    tileID = TM.LoadTexture(tilePath);
                    //Get Tileset Dimensions
                    tempBM = new Bitmap(tilePath);
                    tileSetSizeP = new Size(tempBM.Size.Width, tempBM.Size.Height);
                    tileSetSizeT = new Size(tileSetSizeP.Width / tileSize.Width, tileSetSizeP.Height / tileSize.Height);
                    //AutoScrolls
                    tilePanel.AutoScrollMinSize = tileSetSizeP;

                    //Clear out tile types
                    cBTileType.Items.Clear();
                    //Read in tile types
                    reader.ReadToFollowing("Events");
                    reader.MoveToFirstAttribute();
                    //Read in number of tile types
                    tempInt = Int32.Parse(reader.Value);
                    //Load in tile types
                    for (int i = 0; i < tempInt; i++)
                    {
                        //RGB values for the colors
                        int r, g, b;
                        reader.ReadToFollowing("Event");
                        //Get event
                        reader.MoveToFirstAttribute();
                        tempString = reader.Value;
                        // Get R
                        reader.MoveToNextAttribute();
                        r = Int32.Parse(reader.Value);
                        // Get G
                        reader.MoveToNextAttribute();
                        g = Int32.Parse(reader.Value);
                        // Get B
                        reader.MoveToNextAttribute();
                        b = Int32.Parse(reader.Value);
                        //Add event string to the list box
                        EventString tileType = new EventString(tempString, Color.FromArgb(r, g, b));
                        cBTileType.Items.Add(tileType);
                    }
                    cBTileType.SelectedIndex = 0;

                    //Read each Row
                    for (int h = 0; h < mapSize.Height; h++)
                    {
                        reader.ReadToFollowing("Row");
                        //Read each Tile in the Row
                        for (int w = 0; w < mapSize.Width; w++)
                        {
                            reader.ReadToFollowing("Tile");
                            //Tile Type
                            reader.MoveToFirstAttribute();
                            map[w, h].Id = Int32.Parse(reader.Value);
                            //Tile Source
                            reader.MoveToNextAttribute();
                            tempInt = Int32.Parse(reader.Value);
                            //Tile Source Rect
                            map[w, h].X = (tempInt % tileSetSizeT.Width);
                            map[w, h].Y = (tempInt / tileSetSizeT.Width);
                        }
                    }
                    //Establish blank Entity map
                    Size entMapSize = new Size(mapSize.Width * tileSize.Width / 32, mapSize.Height * tileSize.Height / 32);

                    entMap = new Entity[entMapSize.Width, entMapSize.Height];

                    for (int h = 0; h < entMapSize.Height; h++)
                    {
                        for (int w = 0; w < entMapSize.Width; w++)
                        {
                            //Sets Entities
                            entMap[w, h] = new Entity(w, h, EntityType.ENTITY_BASE);
                        }
                    }
                    int tempX, tempY;
                    //Read in ball
                    reader.ReadToFollowing("Ball");
                    //Read x position
                    reader.MoveToFirstAttribute();
                    ball.X = Int32.Parse(reader.Value);
                    //Read y position
                    reader.MoveToNextAttribute();
                    ball.Y = Int32.Parse(reader.Value);

                    //Read in Red Player Spawns
                    reader.ReadToFollowing("RedPlayers");
                    //Read count
                    reader.MoveToFirstAttribute();
                    tempInt = Int32.Parse(reader.Value);
                    //Load each instance
                    for (int i = 0; i < tempInt; i++)
                    {
                        reader.ReadToFollowing("Instance");
                        reader.MoveToFirstAttribute();
                        tempX = Int32.Parse(reader.Value);
                        reader.MoveToNextAttribute();
                        tempY = Int32.Parse(reader.Value);
                        entMap[tempX, tempY] = new Entity(tempX, tempY, EntityType.PLAYER_RED);
                    }
                    //Read in Blue Player Spawns
                    reader.ReadToFollowing("BluePlayers");
                    //Read count
                    reader.MoveToFirstAttribute();
                    tempInt = Int32.Parse(reader.Value);
                    //Load each instance
                    for (int i = 0; i < tempInt; i++)
                    {
                        reader.ReadToFollowing("Instance");
                        reader.MoveToFirstAttribute();
                        tempX = Int32.Parse(reader.Value);
                        reader.MoveToNextAttribute();
                        tempY = Int32.Parse(reader.Value);
                        entMap[tempX, tempY] = new Entity(tempX, tempY, EntityType.PLAYER_BLUE);
                    }

                    //Read in Boss(es)
                    reader.ReadToFollowing("Boss");
                    //Read count
                    reader.MoveToFirstAttribute();
                    tempInt = Int32.Parse(reader.Value);
                    //Load each instance
                    for (int i = 0; i < tempInt; i++)
                    {
                        reader.ReadToFollowing("Instance");
                        reader.MoveToFirstAttribute();
                        tempX = Int32.Parse(reader.Value);
                        reader.MoveToNextAttribute();
                        tempY = Int32.Parse(reader.Value);
                        EnemySpawn tempGorbi = new EnemySpawn(tempX, tempY, EntityType.ENEMY_GORBACHEV);
                        entMap[tempX, tempY] = tempGorbi;
                    }

                    //Read in Enemies
                    reader.ReadToFollowing("Enemies");
                    //Read count
                    reader.MoveToFirstAttribute();
                    tempInt = Int32.Parse(reader.Value);
                    Point tempWaypoint = new Point();
                    //Load each instance
                    for (int i = 0; i < tempInt; i++)
                    {
                        reader.ReadToFollowing("Instance");
                        reader.MoveToFirstAttribute();
                        tempX = Int32.Parse(reader.Value);
                        reader.MoveToNextAttribute();
                        tempY = Int32.Parse(reader.Value);
                        reader.MoveToNextAttribute();
                        reader.MoveToNextAttribute();
                        tempWaypoint.X = Int32.Parse(reader.Value);
                        reader.MoveToNextAttribute();
                        tempWaypoint.Y = Int32.Parse(reader.Value);

                        EnemySpawn tempCannyble = new EnemySpawn(tempX, tempY, EntityType.ENEMY_CANNYBLE);
                        tempCannyble.Waypoints.Add(tempWaypoint);
                        entMap[tempX, tempY] = tempCannyble;
                    }

                    //Read in Invincible walls
                    reader.ReadToFollowing("WallsInvincible");
                    //Read count
                    reader.MoveToFirstAttribute();
                    tempInt = Int32.Parse(reader.Value);
                    //Load each instance
                    for (int i = 0; i < tempInt; i++)
                    {
                        reader.ReadToFollowing("Instance");
                        reader.MoveToFirstAttribute();
                        tempX = Int32.Parse(reader.Value);
                        reader.MoveToNextAttribute();
                        tempY = Int32.Parse(reader.Value);
                        entMap[tempX, tempY] = new Entity(tempX, tempY, EntityType.WALL_INVINCIBLE);
                    }

                    //Read in tall walls
                    reader.ReadToFollowing("WallsTall");
                    //Read count
                    reader.MoveToFirstAttribute();
                    tempInt = Int32.Parse(reader.Value);
                    //Load each instance
                    for (int i = 0; i < tempInt; i++)
                    {
                        reader.ReadToFollowing("Instance");
                        reader.MoveToFirstAttribute();
                        tempX = Int32.Parse(reader.Value);
                        reader.MoveToNextAttribute();
                        tempY = Int32.Parse(reader.Value);
                        entMap[tempX, tempY] = new Entity(tempX, tempY, EntityType.WALL_TALL);
                    }

                    //Read in short walls
                    reader.ReadToFollowing("WallsShort");
                    //Read count
                    reader.MoveToFirstAttribute();
                    tempInt = Int32.Parse(reader.Value);
                    //Load each instance
                    for (int i = 0; i < tempInt; i++)
                    {
                        reader.ReadToFollowing("Instance");
                        reader.MoveToFirstAttribute();
                        tempX = Int32.Parse(reader.Value);
                        reader.MoveToNextAttribute();
                        tempY = Int32.Parse(reader.Value);
                        entMap[tempX, tempY] = new Entity(tempX, tempY, EntityType.WALL_SHORT);
                    }
                }
            }
        }

        //Loads an image for the map's background
        private void loadBackgroundToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Sets to Resources/Map if not already there
            if (Directory.Exists("..//..//..//..//..//..//NationalBombBallLeague//NationalBombBallLeague//Resources//Maps"))
                Directory.SetCurrentDirectory("..//..//..//..//..//..//NationalBombBallLeague//NationalBombBallLeague//Resources//Maps");

            OpenFileDialog openBox = new OpenFileDialog();
            openBox.Filter = "PNG Files(*.png*)|*.png*";
            openBox.InitialDirectory = Directory.GetCurrentDirectory();

            if (DialogResult.OK == openBox.ShowDialog())
            {
                bgPaths.Add(openBox.FileName);
                BackgroundLayer layer = new BackgroundLayer();
                layer.TextureID = TM.LoadTexture(openBox.FileName);
                //Image dimensions
                Bitmap tempBM = new Bitmap(openBox.FileName);
                layer.Size = tempBM.Size;
                layer.TextureIndex = listBoxBG.Items.Count;
                if (tilePath != null)
                    layer.TextureIndex++;
                //Adds the new layer to the list of layers
                listBoxBG.Items.Add(layer);
            }
        }

        //Loads an image for use as the map's tileset
        private void loadImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Sets to Resources/Map if not already there
            if (Directory.Exists("..//..//..//..//..//..//NationalBombBallLeague//NationalBombBallLeague//Resources//Maps"))
                Directory.SetCurrentDirectory("..//..//..//..//..//..//NationalBombBallLeague//NationalBombBallLeague//Resources//Maps");

            OpenFileDialog openBox = new OpenFileDialog();
            openBox.Filter = "PNG Files(*.png*)|*.png*";
            openBox.InitialDirectory = Directory.GetCurrentDirectory();

            if (DialogResult.OK == openBox.ShowDialog())
            {
                if (tilePath != "null")
                    TM.UnloadTexture(tileID);
                tilePath = openBox.FileName;
                tileID = TM.LoadTexture(openBox.FileName);

                //TileSet Dimensions
                Bitmap tempBM = new Bitmap(openBox.FileName);
                tileSetSizeP = tempBM.Size;
                tileSetSizeT = new Size(tileSetSizeP.Width / tileSize.Width, tileSetSizeP.Height / tileSize.Height);

                //AutoScrolls
                tilePanel.AutoScrollMinSize = tileSetSizeP;
            }
        }

        #endregion

        #region Bells & Whistles
        private void mapPanel_Scroll(object sender, ScrollEventArgs e)
        {
            if (this.Visible)
                RenderMap();
        }

        private void tilePanel_Scroll(object sender, ScrollEventArgs e)
        {
            if (this.Visible)
                RenderTiles();

        }

        private void tilePanel_Resize(object sender, EventArgs e)
        {
            if (this.Visible)
                RenderTiles();
            //Fixes offset caused by scroll bar (not displacement from scrolling)
            D3D.Resize(tilePanel, tilePanel.ClientSize.Width, tilePanel.ClientSize.Height, false);

        }

        private void mapPanel_Resize(object sender, EventArgs e)
        {
            if (this.Visible)
                RenderMap();
            //Fixes offset caused by scroll bar (not displacement from scrolling)
            D3D.Resize(mapPanel, mapPanel.ClientSize.Width, mapPanel.ClientSize.Height, false);
        }
        #endregion

        #region Mouse Controls
        private void tilePanel_MouseClick(object sender, MouseEventArgs e)
        {
            Point offset = new Point(0, 0);

            offset.X += tilePanel.AutoScrollPosition.X;
            offset.Y += tilePanel.AutoScrollPosition.Y;

            Point click = new Point();
            click.X = (e.X - offset.X) / tileSize.Width;
            click.Y = (e.Y - offset.Y) / tileSize.Height;

            //Selects tile
            if (click.X < tileSetSizeT.Width && click.Y < tileSetSizeT.Height)
            {
                selectedRect.X = click.X;
                selectedRect.Y = click.Y;
            }

        }

        private void mapPanel_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
                mouseDown = true;

            if (selectedRect.X >= 0 && selectedRect.X < tileSetSizeT.Width
                && selectedRect.Y >= 0 && selectedRect.Y < tileSetSizeT.Height)
            {
                Point offset = new Point(0, 0);

                offset.X += mapPanel.AutoScrollPosition.X;
                offset.Y += mapPanel.AutoScrollPosition.Y;

                Point click = new Point();
                click.X = (e.X - trCorner.X - offset.X);
                click.Y = (e.Y - trCorner.Y - offset.Y);
                //Makes sure clicking in valid space
                if (click.X < 0 || click.Y < 0)
                    return;
                //Sets tiles
                if (brush == EBrush.TILE_BRUSH)
                {
                    //Finding which tile
                    click.X = click.X / tileSize.Width;
                    click.Y = click.Y / tileSize.Height;

                    if (click.X < mapSize.Width && click.Y < mapSize.Height)
                    {
                        //Left click
                        if (e.Button == System.Windows.Forms.MouseButtons.Left)
                        {
                            //Set clicked tile to the selected rect
                            if (cBTileType.SelectedIndex < 0)
                                map[click.X, click.Y] = new Tile(selectedRect.X, selectedRect.Y);
                            else
                                map[click.X, click.Y] = new Tile(selectedRect.X, selectedRect.Y, cBTileType.SelectedIndex);
                        }
                        //Right click
                        else if (e.Button == System.Windows.Forms.MouseButtons.Right)
                        {
                            //Sets selected brush to the tile clicked
                            cBTileType.SelectedIndex = map[click.X, click.Y].Id;
                            selectedRect.X = map[click.X, click.Y].X;
                            selectedRect.Y = map[click.X, click.Y].Y;
                        }
                    }
                }
                //Sets Entities
                else if (brush == EBrush.ENT_BRUSH)
                {
                    //Finding which entity spot
                    click.X = click.X / 32;
                    click.Y = click.Y / 32;
                    if (click.X < mapSize.Width && click.Y < mapSize.Height)
                    {
                        //Left click
                        if (e.Button == System.Windows.Forms.MouseButtons.Left)
                        {
                            if ((EntityType)cBEntType.SelectedIndex == EntityType.BALL)
                            {
                                ball.X = click.X;
                                ball.Y = click.Y;
                            }
                            else
                                entMap[click.X, click.Y] = new Entity(click.X, click.Y, cBEntType.SelectedIndex);
                        }
                        //Right click
                        else if (e.Button == System.Windows.Forms.MouseButtons.Right)
                        {
                            if (ball.X == click.X && ball.Y == click.Y)
                                cBEntType.SelectedIndex = (int)ball.Type;
                            else
                                cBEntType.SelectedIndex = (int)entMap[click.X, click.Y].Type;
                        }
                    }
                }
                else if (brush == EBrush.ENT_SELECT)
                {
                    //Finding which entity spot
                    click.X = click.X / 32;
                    click.Y = click.Y / 32;

                    if (click.X < mapSize.Width && click.Y < mapSize.Height)
                    {
                        //Left click
                        if (entMap[click.X, click.Y].Type == EntityType.ENEMY_CANNYBLE)
                        {
                            if (selectedCannyble == null)
                                selectedCannyble = new EnemySpawn(entMap[click.X, click.Y].X, entMap[click.X, click.Y].Y, entMap[click.X, click.Y].Type);
                            else
                                selectedCannyble = null;
                        }
                        else if (selectedCannyble != null)
                        {
                            selectedCannyble.Waypoints.Add(click);
                        }
                    }
                }
            }
        }

        private void mapPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (mouseDown == true
                && selectedRect.X >= 0 && selectedRect.X < tileSetSizeT.Width
                && selectedRect.Y >= 0 && selectedRect.Y < tileSetSizeT.Height)
            {
                Point offset = new Point(0, 0);

                offset.X += mapPanel.AutoScrollPosition.X;
                offset.Y += mapPanel.AutoScrollPosition.Y;

                Point click = new Point();
                click.X = (e.X - trCorner.X - offset.X);
                click.Y = (e.Y - trCorner.Y - offset.Y);
                //Makes sure clicking in valid space
                if (click.X < 0 || click.Y < 0)
                    return;
                if (brush == EBrush.TILE_BRUSH)
                {
                    //Finding which tile
                    click.X = click.X / tileSize.Width;
                    click.Y = click.Y / tileSize.Height;

                    if (click.X < mapSize.Width && click.Y < mapSize.Height)
                    {
                        //Set clicked tile to the selected rect
                        if (cBTileType.SelectedIndex < 0)
                            map[click.X, click.Y] = new Tile(selectedRect.X, selectedRect.Y);
                        else
                            map[click.X, click.Y] = new Tile(selectedRect.X, selectedRect.Y, cBTileType.SelectedIndex);
                    }

                }
                //Sets Entities
                else if (brush == EBrush.ENT_BRUSH)
                {
                    //Finding which entity spot
                    click.X = click.X / 32;
                    click.Y = click.Y / 32;

                    if (click.X < mapSize.Width && click.Y < mapSize.Height)
                    {
                        //Left click
                        if (e.Button == System.Windows.Forms.MouseButtons.Left)
                        {
                            if ((EntityType)cBEntType.SelectedIndex == EntityType.BALL)
                            {
                                ball.X = click.X;
                                ball.Y = click.Y;
                            }
                            else
                                entMap[click.X, click.Y] = new Entity(click.X, click.Y, cBEntType.SelectedIndex);
                        }
                        //Right click
                        else if (e.Button == System.Windows.Forms.MouseButtons.Right)
                        {
                            if (ball.X == click.X && ball.Y == click.Y)
                                cBEntType.SelectedIndex = (int)ball.Type;
                            else
                                cBEntType.SelectedIndex = (int)entMap[click.X, click.Y].Type;
                        }
                    }
                }


            }

        }

        private void mapPanel_MouseLeave(object sender, EventArgs e)
        {
            mouseDown = false;
        }

        private void mapPanel_MouseUp(object sender, MouseEventArgs e)
        {
            mouseDown = false;
        }

        #endregion

        //Change in map size
        private void numericUpDownMap_ValueChanged(object sender, EventArgs e)
        {
            Tile[,] tempMap = new Tile[(int)(numericUpDownMapW.Value), (int)(numericUpDownMapH.Value)];

            for (int h = 0; h < numericUpDownMapH.Value; h++)
            {
                for (int w = 0; w < numericUpDownMapW.Value; w++)
                {
                    //Add existing tiles to the new one
                    if (mapSize.Width > w && mapSize.Height > h
                        && numericUpDownMapH.Value > h && numericUpDownMapW.Value > w)
                        tempMap[w, h] = map[w, h];
                    //Add default tile
                    else
                        tempMap[w, h] = new Tile();
                }
            }

            map = tempMap;

            //Set new size
            mapSize.Width = (int)(numericUpDownMapW.Value);
            mapSize.Height = (int)(numericUpDownMapH.Value);

            Size entMapSize = new Size(mapSize.Width * tileSize.Width / 32, mapSize.Height * tileSize.Height / 32);

            //Set new entity map dimensions
            entMap = new Entity[entMapSize.Width, entMapSize.Height];

            for (int h = 0; h < entMapSize.Height; h++)
            {
                for (int w = 0; w < entMapSize.Width; w++)
                {
                    //Sets Entities
                    if (w == 0 || h == 0 || w == entMapSize.Width - 1 || h == entMapSize.Height - 1)
                        entMap[w, h] = new Entity(w, h, EntityType.WALL_INVINCIBLE);
                    else
                        entMap[w, h] = new Entity(w, h, EntityType.ENTITY_BASE);
                }
            }


            //AutoScrolls
            if (tileSize.Width * mapSize.Width > 800
                || tileSize.Height * mapSize.Height > 600)
                mapPanel.AutoScrollMinSize = new Size(tileSize.Width * mapSize.Width,
                    tileSize.Height * mapSize.Height);
            else
                mapPanel.AutoScrollMinSize = new Size(800, 600);

        }

        #region Background Controls
        private void buttonCopyLayer_Click(object sender, EventArgs e)
        {
            //Returns if Index is invalid
            if (listBoxBG.SelectedIndex < 0 || listBoxBG.SelectedIndex >= listBoxBG.Items.Count)
                return;

            BackgroundLayer dummy = (BackgroundLayer)(listBoxBG.Items[listBoxBG.SelectedIndex]);
            BackgroundLayer copy = new BackgroundLayer();

            copy.Location = new Point(dummy.Location.X, dummy.Location.Y);
            copy.Loop = dummy.Loop;
            copy.Name = "Copy of " + dummy.Name;
            copy.ParaSpeed = dummy.ParaSpeed;
            copy.Size = dummy.Size;
            copy.TextureID = dummy.TextureID;
            copy.TextureIndex = dummy.TextureIndex;
            copy.Visible = dummy.Visible;

            listBoxBG.Items.Add(copy);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //Returns if Index is invalid
            if (listBoxBG.SelectedIndex < 0 || listBoxBG.SelectedIndex >= listBoxBG.Items.Count)
                return;

            listBoxBG.Items.RemoveAt(listBoxBG.SelectedIndex);
            listBoxBG.SelectedIndex = -1;
        }

        private void listBoxBG_SelectedIndexChanged(object sender, EventArgs e)
        {
            //Sets defaults if invalid
            if (listBoxBG.SelectedIndex < 0 || listBoxBG.SelectedIndex >= listBoxBG.Items.Count)
            {
                checkBoxVis.Checked = false;
                checkBoxWrap.Checked = false;
                numericUpDownBGX.Value = 0;
                numericUpDownBGY.Value = 0;
                numericUpDownPara.Value = 0;
            }
            else
            {
                //Accesses value at index
                BackgroundLayer dummy = (BackgroundLayer)(listBoxBG.Items[listBoxBG.SelectedIndex]);

                //Set visibility check
                checkBoxVis.Checked = dummy.Visible;
                checkBoxWrap.Checked = dummy.Loop;
                textBoxBGName.Text = dummy.Name;
                numericUpDownBGX.Value = dummy.Location.X;
                numericUpDownBGY.Value = dummy.Location.Y;
                numericUpDownPara.Value = (decimal)dummy.ParaSpeed;
            }


        }

        private void checkBoxVis_CheckedChanged(object sender, EventArgs e)
        {
            //Returns if Index is invalid
            if (listBoxBG.SelectedIndex < 0 || listBoxBG.SelectedIndex >= listBoxBG.Items.Count)
                return;

            //Accesses value at index
            BackgroundLayer dummy = (BackgroundLayer)(listBoxBG.Items[listBoxBG.SelectedIndex]);

            //Set visibility check
            dummy.Visible = checkBoxVis.Checked;

            listBoxBG.Items[listBoxBG.SelectedIndex] = dummy;

        }

        private void checkBoxWrap_CheckedChanged(object sender, EventArgs e)
        {
            //Returns if Index is invalid
            if (listBoxBG.SelectedIndex < 0 || listBoxBG.SelectedIndex >= listBoxBG.Items.Count)
                return;

            //Accesses value at index
            BackgroundLayer dummy = (BackgroundLayer)(listBoxBG.Items[listBoxBG.SelectedIndex]);

            //Set wrap check
            dummy.Loop = checkBoxWrap.Checked;

            listBoxBG.Items[listBoxBG.SelectedIndex] = dummy;
        }

        private void textBoxBGName_TextChanged(object sender, EventArgs e)
        {
            //Returns if Index is invalid
            if (listBoxBG.SelectedIndex < 0 || listBoxBG.SelectedIndex >= listBoxBG.Items.Count)
                return;

            //Accesses value at index
            BackgroundLayer dummy = (BackgroundLayer)(listBoxBG.Items[listBoxBG.SelectedIndex]);

            //Set name
            dummy.Name = textBoxBGName.Text;

            listBoxBG.Items[listBoxBG.SelectedIndex] = dummy;
        }

        private void numericUpDownPara_ValueChanged(object sender, EventArgs e)
        {
            //Returns if Index is invalid
            if (listBoxBG.SelectedIndex < 0 || listBoxBG.SelectedIndex >= listBoxBG.Items.Count)
                return;

            //Accesses value at index
            BackgroundLayer dummy = (BackgroundLayer)(listBoxBG.Items[listBoxBG.SelectedIndex]);

            //Set parallax
            dummy.ParaSpeed = (float)numericUpDownPara.Value;

            listBoxBG.Items[listBoxBG.SelectedIndex] = dummy;
        }

        private void numericUpDownBGOrder_ValueChanged(object sender, EventArgs e)
        {
            //Returns if Index is invalid
            if (listBoxBG.SelectedIndex < 0 || listBoxBG.SelectedIndex >= listBoxBG.Items.Count)
                return;

            //Accesses value at index
            BackgroundLayer dummy = (BackgroundLayer)(listBoxBG.Items[listBoxBG.SelectedIndex]);

            listBoxBG.Items[listBoxBG.SelectedIndex] = dummy;
        }

        private void numericUpDownBGL_ValueChanged(object sender, EventArgs e)
        {
            //Returns if Index is invalid
            if (listBoxBG.SelectedIndex < 0 || listBoxBG.SelectedIndex >= listBoxBG.Items.Count)
                return;

            //Accesses value at index
            BackgroundLayer dummy = (BackgroundLayer)(listBoxBG.Items[listBoxBG.SelectedIndex]);

            //Set location
            dummy.Location = new Point((int)numericUpDownBGX.Value, (int)numericUpDownBGY.Value);


            listBoxBG.Items[listBoxBG.SelectedIndex] = dummy;
        }

        #endregion

        #region Tools
        private void tilePainterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tilePainterToolStripMenuItem.Checked = true;
            entityPainterToolStripMenuItem.Checked = false;
            entitySelectorToolStripMenuItem.Checked = false;
            brush = EBrush.TILE_BRUSH;
        }

        private void entityPainterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tilePainterToolStripMenuItem.Checked = false;
            entityPainterToolStripMenuItem.Checked = true;
            entitySelectorToolStripMenuItem.Checked = false;
            brush = EBrush.ENT_BRUSH;
        }

        #endregion

        private void entitySelectorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tilePainterToolStripMenuItem.Checked = false;
            entityPainterToolStripMenuItem.Checked = false;
            entitySelectorToolStripMenuItem.Checked = true;
            brush = EBrush.ENT_SELECT;
        }

        private void numericUpDownTileSize_ValueChanged(object sender, EventArgs e)
        {
            tileSize.Width = (int)numericUpDownTW.Value;
            tileSize.Height = (int)numericUpDownTH.Value;

            tileSetSizeT = new Size(tileSetSizeP.Width / tileSize.Width, tileSetSizeP.Height / tileSize.Height);

            Size entMapSize = new Size(mapSize.Width * tileSize.Width / 32, mapSize.Height * tileSize.Height / 32);

            //Set new entity map dimensions
            entMap = new Entity[entMapSize.Width, entMapSize.Height];

            for (int h = 0; h < entMapSize.Height; h++)
            {
                for (int w = 0; w < entMapSize.Width; w++)
                {
                    //Sets Entities
                    if (w == 0 || h == 0 || w == entMapSize.Width - 1 || h == entMapSize.Height - 1)
                        entMap[w, h] = new Entity(w, h, EntityType.WALL_INVINCIBLE);
                    else
                        entMap[w, h] = new Entity(w, h, EntityType.ENTITY_BASE);

                }
            }
        }

        private void showTileGridToolStripMenuItem_Click(object sender, EventArgs e)
        {
            showTileGridToolStripMenuItem.Checked = !showTileGridToolStripMenuItem.Checked;
        }

        private void showEntityGridToolStripMenuItem_Click(object sender, EventArgs e)
        {
            showEntityGridToolStripMenuItem.Checked = !showEntityGridToolStripMenuItem.Checked;
        }

        private void showEntitiesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            showEntitiesToolStripMenuItem.Checked = !showEntitiesToolStripMenuItem.Checked;
        }

        private void showTilesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            showTilesToolStripMenuItem.Checked = !showTilesToolStripMenuItem.Checked;
        }

        private void buttonClear_Click(object sender, EventArgs e)
        {
            Size entMapSize = new Size(mapSize.Width * tileSize.Width / 32, mapSize.Height * tileSize.Height / 32);

            //Set new entity map dimensions
            entMap = new Entity[entMapSize.Width, entMapSize.Height];

            for (int h = 0; h < entMapSize.Height; h++)
            {
                for (int w = 0; w < entMapSize.Width; w++)
                {
                    //Sets Entities
                    if (w == 0 || h == 0 || w == entMapSize.Width - 1 || h == entMapSize.Height - 1)
                        entMap[w, h] = new Entity(w, h, EntityType.WALL_INVINCIBLE);
                    else
                        entMap[w, h] = new Entity(w, h, EntityType.ENTITY_BASE);

                }
            }
            //Reset ball pos
            ball.X = 1;
            ball.Y = 1;

        }

        private void buttonAddEvent_Click(object sender, EventArgs e)
        {
            EventString tempES = new EventString();
            tempES.EventColor = button3.BackColor;
            tempES.EventID = textBox1.Text;

            cBTileType.Items.Add(tempES);
        }

        private void helpWindowToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 help = new Form2();
            help.ShowDialog();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            ColorDialog colorBox = new ColorDialog();
            colorBox.Color = button3.BackColor;

            colorBox.ShowDialog();

            button3.BackColor = colorBox.Color;
        }
    }
}
